#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h> 
#include <stdlib.h>       
#include <string.h>
#include <pthread.h>
//#include <sys/sem.h>
#include <errno.h>
#include <sys/ipc.h>
//#include <sys/msg.h>
#include <sys/timeb.h>
#include <sys/socket.h>
//#include <sys/socketvar.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <semaphore.h>
#include <string.h>
#include <termios.h>
#include <linux/input.h>
#include <semaphore.h>
#include <linux/shm.h>
#include <asm/unistd.h>
#include <sys/poll.h>
#include <faad.h>  

#include "common.h"

static int sock = -1;
static struct sockaddr_in addr;	

//extern SystemParam* pgSystemParam;
static void sendToPlay(unsigned char *pcm_data, int pcmDataSize, unsigned char channelCount);

static void *decodeThread_push(void *arg);

int initFaad()
{
		int ret = 0;
		static char tmp[80];
		
   	if( sock == -1 )
   	{
		   	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);		
				addr.sin_family     = AF_INET;
				addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
				addr.sin_port       = htons( 9600 );
				
				if( sock == -1 ) return -1;
		}
		
		/*
		pthread_t ptID;			
		if( pthread_create(&ptID, NULL, decodeThread_push, (void *)0) != 0 )
		{
				printf("create thread failure {%s(%d)}\n",__FILE__,__LINE__);		
				return -3;
		} 
		*/
		
		system("rm -rf /sdcard/1.pcm");
		
		return 0;
}

/*
static void *decodeThread_push(void *arg)
{
		unsigned char *pData;
		int nSize;
		static unsigned long samplesPerSec=0;
		static unsigned char channels=0;
		unsigned char *pcm_data;
		bool initFinish = false;
		NeAACDecFrameInfo frame_info;
		int pcmDataSize;
		int ret;
		
		faacDecHandle faacDecHandle = NeAACDecOpen();
		if( faacDecHandle == NULL )
		{
				printf("NeAACDecOpen failed {%s(%d)}\n",__FILE__,__LINE__);	
				return NULL;
		}	
		
		struct timespec ts;
		struct timeval  tv;	
		
		while( !IsExit() ) 
		{
				gettimeofday(&tv, NULL); 
				
			  ts.tv_sec  = tv.tv_sec + 2;
		    ts.tv_nsec = tv.tv_usec * 1000;		
		    
		    sem_timedwait(&(pgSystemParam->aacPushBlock.m_Semaphore),&ts);		    	
		    
		 		while( pgSystemParam->aacPushBlock.m_Pop->nFlag )
				{						
						//printf("prepare to faad\n");
					
						pData = pgSystemParam->aacPushBlock.m_Pop->pData;
						nSize = pgSystemParam->aacPushBlock.m_Pop->nSize;								
						
						pthread_mutex_lock (&(pgSystemParam->aacPushBlock.m_Lock));
		 				pgSystemParam->aacPushBlock.m_Pop->nFlag = 0;
						pgSystemParam->aacPushBlock.m_Pop = pgSystemParam->aacPushBlock.m_Pop->pNext;
						pthread_mutex_unlock (&(pgSystemParam->aacPushBlock.m_Lock));
		
						if(initFinish == false)
						{
								ret = NeAACDecInit(faacDecHandle,pData,nSize,&samplesPerSec, &channels);	
								if(ret == 0)
								{
										initFinish = true;
								}
								else
								{
										printf("NeAACDecInit failed {%s(%d)}\n",__FILE__,__LINE__);	
								}
						}
						else
						{		
								pcm_data = (unsigned char*)NeAACDecDecode(faacDecHandle, &frame_info, pData,nSize); 
								if( pcm_data && ( frame_info.samples > 0 ) )  	
								{
										pcmDataSize = frame_info.samples * frame_info.channels;
										//printf("faad: frame_info.samples,frame_info.channels = %d,%d\n", frame_info.samples,frame_info.channels);
										
										sendToPlay(pcm_data, pcmDataSize, frame_info.channels);										
								}
						}
				}
		}
		
		if(faacDecHandle != NULL)
		{
				NeAACDecClose(faacDecHandle);	
		}
			
		return NULL;
}
*/

bool initFinish = false;
static faacDecHandle faacDecHandle0 = NULL;

void pushAudioData(unsigned char *pData,int nSize)
{
		static unsigned long samplesPerSec=0;
		static unsigned char channels=0;
		unsigned char *pcm_data;
		NeAACDecFrameInfo frame_info;
		int pcmDataSize;
		int ret;
			
		if( faacDecHandle0 == NULL )
		{
				faacDecHandle0 = NeAACDecOpen();
				printf("NeAACDecOpen failed {%s(%d)}\n",__FILE__,__LINE__);	
				
				if( faacDecHandle0 == NULL )
				{
						return;
				}
		}	
		
		if(initFinish == false)
		{
				ret = NeAACDecInit(faacDecHandle0,pData,nSize,&samplesPerSec, &channels);	
				if(ret == 0)
				{
						initFinish = true;
				}
				else
				{
						printf("NeAACDecInit failed {%s(%d)}\n",__FILE__,__LINE__);	
				}
		}
		else
		{		
				pcm_data = (unsigned char*)NeAACDecDecode(faacDecHandle0, &frame_info, pData,nSize); 
				if( pcm_data && ( frame_info.samples > 0 ) )  	
				{
						pcmDataSize = frame_info.samples * frame_info.channels;
						//printf("faad: frame_info.samples,frame_info.channels = %d,%d\n", frame_info.samples,frame_info.channels);
						
						sendToPlay(pcm_data, pcmDataSize, frame_info.channels);										
				}
		}
}


static void sendToPlay(unsigned char *pcm_data, int pcmDataSize, unsigned char channelCount)
{
		if( sock == -1 )
   	{
		   	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);		
				addr.sin_family     = AF_INET;
				addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
				addr.sin_port       = htons( 9600 );
				
				if( sock == -1 )
				{
						writeLog("can not bind 127.0.0.1:9600 !\n", __FILE__, __LINE__);	
						return;
				}
		}
		
		static unsigned char pcmPackageDataBuf[1600];
		static socklen_t svrlen = sizeof(struct sockaddr_in);
		unsigned int sampleRate = 44100;
		unsigned int samp_count = 0;
		int total = (pcmDataSize + 1024 - 1) / 1024;
		int tmpLen, leftLen, count;
		int sendLen = 0;
		unsigned char flag;
		
		pcmPackageDataBuf[0] = 0xA2;
		pcmPackageDataBuf[1] = sampleRate >> 8;
		pcmPackageDataBuf[2] = sampleRate;
		pcmPackageDataBuf[3] = channelCount;
		
		pcmPackageDataBuf[4] = samp_count >> 24;
		pcmPackageDataBuf[5] = samp_count >> 16;
		pcmPackageDataBuf[6] = samp_count >> 8;
		pcmPackageDataBuf[7] = samp_count;
		
		pcmPackageDataBuf[8] = pcmDataSize >> 8;
		pcmPackageDataBuf[9] = pcmDataSize;
		pcmPackageDataBuf[10] = total >> 8;
		pcmPackageDataBuf[11] = total;
		
		int maxCountNumber = total -1;
		for(count = 0; count < total; count ++)
		{
				if(count == maxCountNumber)
				{
						flag = 3;
				}
				else if(count == 0)
				{
						flag = 1;
				}
				else
				{
						flag = 2;
				}
				
				leftLen = pcmDataSize - sendLen;
				tmpLen = (leftLen> 1024) ? 1024 : leftLen;
				
				pcmPackageDataBuf[12] = count >> 8;
				pcmPackageDataBuf[13] = count;
				pcmPackageDataBuf[14] = flag;
				
				//printf("pcmDataSize,count,total,tmpLen,flag,maxCountNumber = %d,%d,%d,%d,%d,%d\n", pcmDataSize,count,total,tmpLen,flag,maxCountNumber);
				
				memcpy(pcmPackageDataBuf + 15, pcm_data + sendLen, tmpLen);
				
				sendto(sock,pcmPackageDataBuf, 15 + tmpLen,0,(const sockaddr*)&addr,svrlen);
				
				sendLen += tmpLen;
				
				/*char name[222];
				FILE *fout=NULL;
				sprintf(name,"/sdcard/1.pcm");
				if(fout==NULL) fout = fopen(name, "ab");
			  if(fout)fwrite(pcmPackageDataBuf + 15, tmpLen, 1, fout);
			  if(fout)fclose(fout);*/
		}
}